{
  //声明一个接口, 名字为 BoyFriend , 接口名称与类名命名的规则相同, 使用大驼峰
  interface BoyFriend {
    readonly id: number;
    name: string;
    age: number;
    car?: string;
    //设置方法约束   let fn: (a: number, b: number) => number;
    cook: () => void;
    // cook(): void;
  }

  //声明一个对象. 声明一个类型为 BoyFriend 的变量.
  let me: BoyFriend = {
    id: 1,
    name: "吴彦祖",
    age: 28,
    cook: () => {
      console.log("我会做煮方便面~~");
    },
  };

  let you: BoyFriend = {
    id: 2,
    name: "金城武",
    age: 30,
    car: "金杯..",
    cook() {
      console.log("我会做蛋炒饭~~~");
    },
  };

  //使用对象时
  // me.name // 这里有代码提示
  // me?.car // ?.  可选链操作符

  //测试 readonly
  // me.id = 3;
}

{
  //声明一个基础信息的接口
  interface BaseInfo {
    name: string;
    age: number;
  }

  //声明一个接口, 名字为 BoyFriend , 接口名称与类名命名的规则相同, 使用大驼峰
  interface BoyFriend extends BaseInfo {
    readonly id: number;
    car?: string;
    //设置方法约束   let fn: (a: number, b: number) => number;
    cook: () => void;
    // cook(): void;
  }

  //接口也可以继承
  interface Programer extends BaseInfo {
    program: () => void;
  }

  //类与接口的结合使用  implements 『实现的』,  并且在 js 中 implements 是一个保留字
  class Test implements BoyFriend, Programer {
    id: number;
    name: string;
    age: number;

    constructor(id: number, name: string, age: number) {
      this.id = id;
      this.name = name;
      this.age = age;
    }

    cook() {
      console.log("葱油拌面~~");
    }

    program() {
      console.log("我可以编写 TypeScript...");
    }
  }

  //实例化
  let t = new Test(28, "赵又廷", 35);

  // t.
}

{
  //接口的多次声明
  interface A {
    a: number;
    b: string;
  }

  //如果接口进行了多次声明, 不会报错的, 对接口进行自动合并
  interface A{
    c: number;
  }

  interface A{
    d: 'left' | 'right' | 'center'
  }

  let v1: A = {
    a: 1231,
    b: "xxx",
    c: 1212,
    d: 'center'
  };
}
